package com.sad.jetpack.v1.promise;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 一个实现了 Promise/A+ 规范的异步操作类。
 * 它代表了一个最终可能完成（fulfilled）或失败（rejected）的操作及其结果值。
 * @param <T> Promise 解决（resolve）时返回的值的类型。
 */
public class Promise<T> {

    /**
     * Promise 的内部状态，表示其生命周期。
     */
    private enum State {
        PENDING,   // 初始状态，既不是成功，也不是失败。
        FULFILLED, // 操作成功完成。
        REJECTED   // 操作失败。
    }

    // Promise 的当前状态，使用 volatile 保证多线程间的可见性。
    private volatile State state = State.PENDING;
    // Promise 成功时的最终值。
    private T value;
    // Promise 失败时的原因（通常是一个异常）。
    private Throwable reason;

    // 存储当 Promise 成功时需要执行的回调函数列表。
    private final List<Consumer<T>> onFulfilledCallbacks = new ArrayList<>();
    // 存储当 Promise 失败时需要执行的回调函数列表。
    private final List<Consumer<Throwable>> onRejectedCallbacks = new ArrayList<>();

    // 全局共享的默认线程池，用于执行异步任务和回调。
    private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();
    // 全局共享的、用于处理超时的调度器。
    private static final ScheduledExecutorService TIMEOUT_SCHEDULER = Executors.newSingleThreadScheduledExecutor();

    // 每个 Promise 实例可以关联一个特定的执行器，用于执行其回调。
    private java.util.concurrent.Executor executor = null;

    /**
     * Promise 的主要构造函数。
     * @param task 一个函数式接口，包含了异步操作的逻辑。
     */
    public Promise(ExecutorTask<T> task) {
        // 将用户的任务提交到默认线程池中异步执行。
        THREAD_POOL.submit(() -> {
            try {
                // 执行用户的异步任务，并传入 resolve 和 reject 方法。
                task.execute(this::resolve, this::reject);
            } catch (Exception e) {
                // 如果在执行器内部直接抛出异常，则将 Promise 置为 rejected 状态。
                this.reject(e);
            }
        });
    }

    /**
     * 私有构造函数，用于在内部创建新的 Promise 实例（例如在 then, handle 等方法中）。
     */
    private Promise() {}

    /**
     * 将 Promise 的状态从 PENDING 变为 FULFILLED。
     * 这是一个同步方法，以确保状态改变的原子性。
     * @param value 异步操作成功的结果。
     */
    private synchronized void resolve(T value) {
        if (state != State.PENDING) return;
        this.state = State.FULFILLED;
        this.value = value;
        // 决定使用哪个线程池：优先使用实例自带的，否则使用全局默认的。
        java.util.concurrent.Executor currentExecutor = this.executor != null ? this.executor : THREAD_POOL;
        // 异步执行所有注册的 onFulfilled 回调。
        onFulfilledCallbacks.forEach(callback -> currentExecutor.execute(() -> callback.accept(value)));
        clearCallbacks();
    }

    /**
     * 将 Promise 的状态从 PENDING 变为 REJECTED。
     * 这是一个同步方法，以确保状态改变的原子性。
     * @param reason 异步操作失败的原因。
     */
    private synchronized void reject(Throwable reason) {
        if (state != State.PENDING) return;
        this.state = State.REJECTED;
        this.reason = reason;
        java.util.concurrent.Executor currentExecutor = this.executor != null ? this.executor : THREAD_POOL;
        onRejectedCallbacks.forEach(callback -> currentExecutor.execute(() -> callback.accept(reason)));
        clearCallbacks();
    }

    // --- then 方法重载 ---
    public <R> Promise<R> then(String stepName, Function<T, ?> onFulfilled) {
        return then(stepName, onFulfilled, null, null);
    }

    public <R> Promise<R> then(Function<T, ?> onFulfilled) {
        return then(null, onFulfilled, null, null);
    }

    public <R> Promise<R> then(Function<T, ?> onFulfilled, Consumer<Throwable> onRejected) {
        return then(null, onFulfilled, onRejected, null);
    }

    public <R> Promise<R> then(Function<T, ?> onFulfilled, java.util.concurrent.Executor executor) {
        return then(null, onFulfilled, null, executor);
    }

    /**
     * `then` 方法的核心实现，处理链式调用、状态传递和错误包装。
     * @param stepName    步骤名称。
     * @param onFulfilled 成功回调。
     * @param onRejected  失败回调。
     * @param executor    执行此步骤回调的自定义线程池。
     * @param <R>         返回的新 Promise 的类型。
     * @return 新的 Promise。
     */
    private <R> Promise<R> then(String stepName, Function<T, ?> onFulfilled, Consumer<Throwable> onRejected, java.util.concurrent.Executor executor) {
        Promise<R> nextPromise = new Promise<>();
        nextPromise.executor = executor; // 将执行器传递给链中的下一个 Promise

        addFulfilledCallback(value -> {
            try {
                Object result = onFulfilled.apply(value);
                if (result instanceof Promise) {
                    ((Promise<R>) result).then(
                        res -> {
                            nextPromise.resolve(res);
                            return null;
                        },
                        (Consumer<Throwable>) nextPromise::reject
                    );
                } else {
                    nextPromise.resolve((R) result);
                }
            } catch (Exception e) {
                nextPromise.reject(new PromiseStepException(getStepName(stepName), e));
            }
        });

        addRejectedCallback(error -> {
            if (onRejected != null) {
                try {
                    onRejected.accept(error);
                    nextPromise.resolve(null);
                } catch (Exception e) {
                    nextPromise.reject(new PromiseStepException(getStepName(stepName, "onRejected"), e));
                }
            } else {
                nextPromise.reject(error);
            }
        });

        return nextPromise;
    }

    // --- except 方法重载 ---
    public Promise<T> except(Consumer<Throwable> onRejected) {
        return except(onRejected, null);
    }

    public Promise<T> except(Consumer<Throwable> onRejected, java.util.concurrent.Executor executor) {
        Promise<T> nextPromise = new Promise<>();
        nextPromise.executor = executor;
        addFulfilledCallback(nextPromise::resolve);
        addRejectedCallback(reason -> {
            try {
                onRejected.accept(reason);
                nextPromise.resolve(this.value);
            } catch (Exception e) {
                nextPromise.reject(e);
            }
        });
        return nextPromise;
    }

    // --- lastly 方法重载 ---
    public Promise<T> lastly(Runnable onFinally) {
        return lastly(onFinally, null);
    }

    public Promise<T> lastly(Runnable onFinally, java.util.concurrent.Executor executor) {
        Promise<T> nextPromise = new Promise<>();
        nextPromise.executor = executor;
        addFulfilledCallback(value -> {
            try {
                onFinally.run();
                nextPromise.resolve(value);
            } catch (Exception e) {
                nextPromise.reject(e);
            }
        });
        addRejectedCallback(reason -> {
            try {
                onFinally.run();
                nextPromise.reject(reason);
            } catch (Exception e) {
                nextPromise.reject(e);
            }
        });
        return nextPromise;
    }

    // --- handle 方法 ---
    public <R> Promise<R> handle(BiFunction<? super T, Throwable, ? extends R> fn) {
        return handle(fn, null);
    }

    /**
     * 注册一个无论 Promise 成功还是失败都会执行的回调，并返回一个新的 Promise。
     * 类似于 `finally`，但它可以接收上一步的结果或异常，并返回一个新的结果。
     * @param fn       一个 BiFunction，接收 (结果, 异常) 作为参数，并返回一个新的结果。
     * @param executor 执行此回调的自定义线程池。
     * @param <R>      返回的新 Promise 的类型。
     * @return 新的 Promise。
     */
    public <R> Promise<R> handle(BiFunction<? super T, Throwable, ? extends R> fn, java.util.concurrent.Executor executor) {
        Promise<R> nextPromise = new Promise<>();
        nextPromise.executor = executor;

        Consumer<T> successCallback = (value) -> {
            try {
                R result = fn.apply(value, null);
                nextPromise.resolve(result);
            } catch (Exception e) {
                nextPromise.reject(e);
            }
        };

        Consumer<Throwable> errorCallback = (error) -> {
            try {
                R result = fn.apply(null, error);
                nextPromise.resolve(result);
            } catch (Exception e) {
                nextPromise.reject(e);
            }
        };

        addFulfilledCallback(successCallback);
        addRejectedCallback(errorCallback);

        return nextPromise;
    }

    // --- orTimeout 方法 ---
    /**
     * 如果 Promise 在指定的超时时间内没有完成，则以 TimeoutException 将其拒绝。
     * @param timeout 超时时长
     * @param unit    时间单位
     * @return 一个新的、具有超时能力的 Promise。
     */
    public Promise<T> orTimeout(long timeout, TimeUnit unit) {
        Promise<T> newPromise = new Promise<>();

        // 安排一个任务，在超时后拒绝新的 Promise
        final ScheduledFuture<?> timeoutFuture = TIMEOUT_SCHEDULER.schedule(() -> {
            // 检查并设置状态，确保 reject 只被调用一次
            if (newPromise.state == State.PENDING) {
                newPromise.reject(new TimeoutException("Promise timed out after " + timeout + " " + unit.toString().toLowerCase()));
            }
        }, timeout, unit);

        // 监听当前 Promise 的结果
        this.then(val -> {
            timeoutFuture.cancel(false); // 成功，取消超时任务
            newPromise.resolve(val);
            return null;
        }, (Consumer<Throwable>) err -> {
            timeoutFuture.cancel(false); // 失败，也取消超时任务
            newPromise.reject(err);
        });

        return newPromise;
    }

    private synchronized void addFulfilledCallback(Consumer<T> callback) {
        if (state == State.FULFILLED) {
            java.util.concurrent.Executor currentExecutor = this.executor != null ? this.executor : THREAD_POOL;
            currentExecutor.execute(() -> callback.accept(value));
        } else if (state == State.PENDING) {
            onFulfilledCallbacks.add(callback);
        }
    }

    private synchronized void addRejectedCallback(Consumer<Throwable> callback) {
        if (state == State.REJECTED) {
            java.util.concurrent.Executor currentExecutor = this.executor != null ? this.executor : THREAD_POOL;
            currentExecutor.execute(() -> callback.accept(reason));
        } else if (state == State.PENDING) {
            onRejectedCallbacks.add(callback);
        }
    }

    private synchronized void clearCallbacks() {
        onFulfilledCallbacks.clear();
        onRejectedCallbacks.clear();
    }

    private String getStepName(String providedName, String suffix) {
        String baseName = getStepName(providedName);
        return baseName + "#" + suffix;
    }

    private String getStepName(String providedName) {
        if (providedName != null && !providedName.isEmpty()) {
            return providedName;
        }
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (int i = 2; i < stackTrace.length; i++) {
            StackTraceElement element = stackTrace[i];
            if (!element.getClassName().equals(Promise.class.getName())) {
                return String.format("%s.%s(L%d)",
                    element.getClassName(),
                    element.getMethodName(),
                    element.getLineNumber());
            }
        }
        return "Unknown Step";
    }

    public static <T> Promise<T> resolved(T value) {
        Promise<T> p = new Promise<>();
        p.resolve(value);
        return p;
    }

    public static <T> Promise<T> rejected(Throwable reason) {
        Promise<T> p = new Promise<>();
        p.reject(reason);
        return p;
    }

    // --- all 和 race 方法 ---
    @SafeVarargs
    public static <T> Promise<List<T>> all(Promise<T>... promises) {
        return all(Arrays.asList(promises));
    }

    public static <T> Promise<List<T>> all(List<Promise<T>> promises) {
        return new Promise<>((resolve, reject) -> {
            if (promises.isEmpty()) {
                resolve.accept(new ArrayList<>());
                return;
            }

            List<T> results = new ArrayList<>(Collections.nCopies(promises.size(), null));
            AtomicInteger completedCount = new AtomicInteger(0);
            AtomicBoolean failed = new AtomicBoolean(false);

            for (int i = 0; i < promises.size(); i++) {
                final int index = i;
                promises.get(i).then(val -> {
                    if (failed.get()) return null;
                    synchronized (results) {
                        results.set(index, val);
                    }
                    if (completedCount.incrementAndGet() == promises.size()) {
                        resolve.accept(results);
                    }
                    return null;
                }, (Consumer<Throwable>) err -> {
                    if (failed.compareAndSet(false, true)) {
                        reject.accept(err);
                    }
                });
            }
        });
    }

    @SafeVarargs
    public static <T> Promise<T> race(Promise<T>... promises) {
        return race(Arrays.asList(promises));
    }

    public static <T> Promise<T> race(List<Promise<T>> promises) {
        return new Promise<>((resolve, reject) -> {
            AtomicBoolean settled = new AtomicBoolean(false);
            for (Promise<T> p : promises) {
                p.then(
                    val -> {
                        if (settled.compareAndSet(false, true)) {
                            resolve.accept(val);
                        }
                        return null;
                    },
                    (Consumer<Throwable>) err -> {
                        if (settled.compareAndSet(false, true)) {
                            reject.accept(err);
                        }
                    }
                );
            }
        });
    }

    /**
     * 一个函数式接口，定义了 Promise 构造函数中执行器的签名。
     * @param <T> Promise 的结果类型。
     */
    @FunctionalInterface
    public interface ExecutorTask<T> {
        /**
         * 执行异步任务。
         * @param resolve 当任务成功时调用此函数。
         * @param reject  当任务失败时调用此函数。
         */
        void execute(Consumer<T> resolve, Consumer<Throwable> reject);
    }
}
